﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;

public class RewardAnim : MonoBehaviour {

    public int type = 1;

    [SerializeField]
    AnimationCurve m_CurveToTransit = AnimationCurve.EaseInOut(0, 0, 1, 1);

    [SerializeField]
    AnimationCurve m_CurveToTarget = AnimationCurve.EaseInOut(0,0,1,1);

    // Use this for initialization
    void Start () {
		
	}

    /// <summary>
    /// 
    /// </summary>
    /// <param name="rect"></param>
    /// <param name="targetPos"></param>
    /// <param name="roundDir">大致方向</param>
    /// <param name="randomRange">中转点随机范围</param>
    /// <param name="time"></param>
    /// <param name="OnEnd"></param>
    public void PlayFlyToAnim(Transform rect,Vector3 targetPos,Vector3 roundDir, float transitPosRange, float time,Action OnEnd)
    {
       // float transitPro = UnityEngine.Random.Range(-randomRange, randomRange);
      //  Vector3 transitCenter = rect.position + (targetPos - rect.position) * transitPro;

       // Debug.LogError("roundDir:"+roundDir);
        if (type == 0)
        { 
            Vector3 transitPos = GetRandomRangePos(rect.position, 100, 100);
            float timeRate = (targetPos - transitPos).magnitude / (targetPos - rect.position).magnitude;
            time *= timeRate;

            List<Vector2> points = new List<Vector2>();
            points.Add(rect.position);
            points.Add(transitPos);
            points.Add(targetPos);
            Func<float, float> curveFunc = InterpolationCalculate.NewtonInterpolation(points.ToArray());

            StartCoroutine(PlayFlyToAnimNewTon(rect, targetPos, time, curveFunc));

            DoActionDelay.DelayAction(time, OnEnd);
        }
        else if(type == 1)
        {
            Vector3 transitPos = Vector3.zero;
            if (roundDir == Vector3.zero)
                transitPos = GetRandomRangePos(rect.position, transitPosRange, transitPosRange);
            else
                transitPos = GetRandomRangePos(rect.position, transitPosRange, roundDir);

            float timeRate = (targetPos - transitPos).magnitude / (targetPos - rect.position).magnitude;
            time *= timeRate;
            StartCoroutine(PlayFlyToAnimAddForce(rect, targetPos, transitPos, time,m_CurveToTransit,m_CurveToTarget));

            DoActionDelay.DelayAction(time, OnEnd);
        }
    }

    public float forceToTargetBegin = 0.1f;
    public float forceToTargetMul = 1.1f;
    public float forceToTransitBegin = 0.1f;
    public float forceToTransitMul = 0.9f;

    public static IEnumerator PlayFlyToAnimAddForce(Transform rect, Vector3 targetPos, Vector3 transitPos,
        float totalTime, AnimationCurve m_CurveToTransit, AnimationCurve m_CurveToTarget,
        float forceToTargetBegin = 0.08f, float forceToTargetMul = 1.1f, float forceToTransitBegin = 0.92f,
        float forceToTransitMul = 0.9f)
    {
        return PlayFlyToAnimAddForce(rect, ()=> targetPos,  transitPos,
         totalTime,  m_CurveToTransit,  m_CurveToTarget,
         forceToTargetBegin ,  forceToTargetMul ,  forceToTransitBegin ,
         forceToTransitMul );
    }
    public static IEnumerator PlayFlyToAnimAddForce(Transform rect, Func<Vector3> getTargetPosFunc, Vector3 transitPos, float totalTime, AnimationCurve m_CurveToTransit, AnimationCurve m_CurveToTarget,
        float forceToTargetBegin = 0.1f, float forceToTargetMul = 1.1f, float forceToTransitBegin = 0.9f, float forceToTransitMul = 0.9f)
    {
        if (getTargetPosFunc == null)
        {
            GameDebug.LogError("getTargetPosFunc == null");
            yield break;
        }

        float transitRate = 0.3f;// UnityEngine.Random.Range(0.3f, 0.6f);
        Vector3 beginPos = rect.position;
        float timer = 0;

        float transitTime = totalTime * transitRate;

        float forceToTarget = forceToTargetBegin;
        float forceToTransit = forceToTransitBegin;

        Vector3 realTransitPos = transitPos;


        while (timer < totalTime)
        {
            yield return null;

            if (rect == null)
                yield break;

            timer += Time.deltaTime;

            float rate = timer / totalTime;

            if (rate < transitRate)
            {
                float x = rate / transitRate;
                float y = m_CurveToTransit.Evaluate(x);
                Vector3 pos = Vector3.Lerp(beginPos, transitPos, y);
                pos = Vector3.Lerp(pos, getTargetPosFunc(), forceToTarget * x);
                forceToTarget *= forceToTargetMul;
                rect.position = pos;

                realTransitPos = pos;
            }
            else
            {
                float x = (rate - transitRate) / (1 - transitRate);
                float y = m_CurveToTarget.Evaluate(x);
                Vector3 pos = Vector3.Lerp(realTransitPos, getTargetPosFunc(), y);
                pos = Vector3.Lerp(pos, pos + transitPos - beginPos, forceToTransit * x);
                forceToTransit *= forceToTransitMul;

                rect.position = pos;

            }
        }

    }


    /// <summary>
    /// 应用插值公式计算运动轨迹
    /// </summary>
    /// <param name="rect"></param>
    /// <returns></returns>
    IEnumerator PlayFlyToAnimNewTon(Transform rect, Vector3 targetPos, float totalTime, Func<float, float> curveFunc)
    {
        if (rect == null || curveFunc == null)
            yield break;

        float transitRate = UnityEngine.Random.Range(0.3f, 0.6f);

        Vector3 beginPos = rect.position;
        float timer = 0;
        while (timer < totalTime)
        {
            yield return null;
            timer += Time.deltaTime;

            float rate = timer / totalTime;
            float rateInCurve = m_CurveToTarget.Evaluate(rate);
            float x = Mathf.Lerp(beginPos.x, targetPos.x, rateInCurve); 
            float y = curveFunc(x);
            rect.position = new Vector3(x, y, beginPos.z);
        }


    }
    Vector3 GetRandomRangePos(Vector3 pos, float randomRangeM,  Vector3 roundDir)
    {
        //指定方向
        float randomM = UnityEngine.Random.Range(randomRangeM/2f, randomRangeM);
        Vector3 dirRandom = roundDir.normalized * randomM;
        //float minX = (roundDir.x > 0) ? 0 : -randomRangeX;
        //float maxX = (roundDir.x > 0) ? randomRangeX : 0;

        //float minY = (roundDir.y > 0) ? 0 : -randomRangeY;
        //float maxY = (roundDir.y > 0) ? randomRangeY : 0;

        //float randomX = UnityEngine.Random.Range(minX, maxX);
        //float randomY = UnityEngine.Random.Range(minY, maxY);
        //randomPos = pos + new Vector2(randomX, randomY);
        Vector3 randomPos = pos + dirRandom;
        return randomPos;
    }
    /// <summary>
    /// 获取一定范围内随机位置
    /// </summary>
    /// <param name="pos"></param>
    /// <param name="randomRange"></param>
    /// <param name="roundDir">大致方向</param>
    /// <returns></returns>
    Vector2 GetRandomRangePos(Vector2 pos,float randomRangeX, float randomRangeY)
    {
        Vector2 randomPos = Vector2.zero;

        float randomX = UnityEngine.Random.Range(-randomRangeX, randomRangeX);
        float randomY = UnityEngine.Random.Range(-randomRangeY, randomRangeY);
        randomPos = pos + new Vector2(randomX, randomY);
      
        return randomPos;
    }

    /// <summary>
    /// 使保证在屏幕内
    /// </summary>
    /// <param name="pos"></param>
    /// <returns></returns>
    Vector2 EnsureInScreen(Vector2 pos)
    {
        var rect = new UnityEngine.GameObject().AddComponent<RectTransform>();
        var originalPos = rect.position;
        var viewportPos = PanelCommon.uiCamera.WorldToViewportPoint(transform.position);
        if(viewportPos.x < 0)
        {
            rect.position = pos;
            var aPos = rect.anchoredPosition;
            aPos.x = -aPos.x;
            rect.anchoredPosition = aPos;
            pos = rect.position;
        }
        if(viewportPos.x > 1)
        {
            rect.position = pos;
            var aPos = rect.anchoredPosition;
            aPos.x = 540 - (aPos.x - 540);
            rect.anchoredPosition = aPos;
            pos = rect.position;
        }
        return pos;
    }

    // Update is called once per frame
    void Update () {
		
	}
}
